package org.rulix.ogame.player.core.http;

import java.io.FileInputStream;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.rulix.ogame.player.api.OgameFleetMovement;
import org.rulix.ogame.player.api.OgamePlanet;
import org.rulix.ogame.player.core.OgameException;
import org.rulix.ogame.player.core.OgameResponseHelper;
import org.rulix.ogame.player.core.OgameResponseParser;
import org.rulix.ogame.player.core.OgameSession;
import org.rulix.ogame.player.core.info.OgameDataHelper;

public class OgameHttpExecutor {
	
	private HttpClient httpClient = null;
	
	public OgameHttpExecutor(HttpClient httpClient) {
		this.httpClient = httpClient;
	}
	
	private StringBuilder executRequestAndCollectContent(HttpUriRequest httpRequest, HttpClient httpClient) throws OgameException {
		HttpResponse response = null;
		StringBuilder output = null;
		try {
			System.out.println("--HTTP REQUEST: " + httpRequest.getURI().toString());
			Thread.sleep(1000);
			response = httpClient.execute(httpRequest);
			output = OgameDataHelper.readInputStream(response.getEntity()
					.getContent());
			System.out.println("--HTTP RESPONSE: " + response.getStatusLine().toString());
			if ( response.getHeaders("Location") != null && response.getHeaders("Location").length != 0 )
				System.out.println("  --Location: " + response.getHeaders("Location")[0].getValue());
			
		} catch (Exception e) {
			throw new OgameException("Cannot execute HTTP Request",e);
		} finally {
			if (response != null) {
				try { response.getEntity().getContent().close();} catch (Exception e2) {}
			}
		}
		return output;
	}
	
	public OgameSession login(String server, String user, String password) throws OgameException {
		OgameSession ogameSession;
		try {
			ogameSession = new OgameSession();
			ogameSession.setLogin(user);
			ogameSession.setPassword(password);
			ogameSession.setOgameServer(server);
			ogameSession.setLoggedIn(false);
			
			HttpPost request = OgameRequestFactory.getLoginRequest(ogameSession);
			HttpResponse response = httpClient.execute(request);

			OgameResponseHelper orHelper = new OgameResponseHelper();
			boolean loggedIn = orHelper.isLoggedIn(response, ogameSession);

			if (loggedIn){
				DefaultHttpClient cl = (DefaultHttpClient)httpClient;
				for (Cookie cookie : cl.getCookieStore().getCookies()) {
					if ( cookie.getName().equals("PHPSESSID") ){
						ogameSession.setSessionId(cookie.getValue());
						ogameSession.setLoggedIn(true);
					}
				}
			} 
			
			response.getEntity().getContent().close();
		} catch (Exception e) {
			throw new OgameException("Cannot login user", e);
		}
		return ogameSession;
	}
	
	public List<OgameFleetMovement> getFleetMovements(OgameSession ogameSession) throws OgameException {
		
		try {
			HttpClient client = this.httpClient;
			
			HttpGet request = OgameRequestFactory.getEventListRequest(ogameSession);
			//HttpResponse response = client.execute(request);
			
			//TODO: check response is not an error response.
			OgameDataHelper odh = new OgameDataHelper();
			
			//StringBuilder output = OgameDataHelper.readInputStream(response.getEntity().getContent());
			StringBuilder output = OgameDataHelper.readInputStream(new FileInputStream("./test_resources/Ataque_Ogame.html"));
			//StringBuilder output = OgameDataHelper.readInputStream(response.getEntity().getContent());
			List<OgameFleetMovement> list = odh.getFleetMovements(output);
//			response.getEntity().getContent().close();
			return list;
			
		} catch (Exception e) {
			throw new OgameException("Cannot login user", e);
		}
	}
	
	public void initialize(OgameSession ogameSession) throws OgameException {
		HttpGet request = OgameRequestFactory.getOverviewRequest(ogameSession);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
		
		OgameResponseParser orp = new OgameResponseParser(sb.toString());
		List<OgamePlanet> planetList = orp.getPlanets();
		
		ogameSession.setPlanets(planetList);				
	}

	public void getResources(OgameSession ogameSession, OgamePlanet ogamePlanet) throws OgameException {
		HttpGet request = OgameRequestFactory.getOverviewPlanetRequest(ogameSession, ogamePlanet);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
		
		OgameResponseParser orp = new OgameResponseParser(sb.toString());
		
		long metal = orp.getMetalResources();
		long crystal = orp.getCrystalResources();
		long deuterium = orp.getDeuteriumResources();
		
		ogamePlanet.setMetal(metal);
		ogamePlanet.setCrystal(crystal);
		ogamePlanet.setDeuterium(deuterium);
	}

	public void getBuildings(OgameSession ogameSession, OgamePlanet ogamePlanet) throws OgameException{
		HttpGet request = OgameRequestFactory.getBuildingsRequest(ogameSession, ogamePlanet);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
		
		OgameResponseParser orp = new OgameResponseParser(sb.toString());
		
		ogamePlanet.setMetalMine(orp.getMetalMineLevel());
		ogamePlanet.setCrystalMine(orp.getCrystalMineLevel());
		ogamePlanet.setDeuteriumSynthesizer(orp.getDeuteriumSynthLevel());
		ogamePlanet.setSolarPlant(orp.getSolarPlantLevel());
		ogamePlanet.setFusionReactor(orp.getFusionPlantLevel());
		ogamePlanet.setSolarSatellite(orp.getSolarSatellieLevel());
		ogamePlanet.setMetalStorage(orp.getMetalStorageLevel());
		ogamePlanet.setCrystalStorage(orp.getCrystalStorageLevel());
		ogamePlanet.setDeuteriumTank(orp.getDeuteriumStorageLevel());
	}
	
	public void getFacilities(OgameSession ogameSession, OgamePlanet ogamePlanet) throws OgameException{
		HttpGet request = OgameRequestFactory.getFacilitiesRequest(ogameSession, ogamePlanet);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
		
		OgameResponseParser orp = new OgameResponseParser(sb.toString());
		
		ogamePlanet.setRoboticsFactory(orp.getRobotFactoryLevel());
		ogamePlanet.setShipyard(orp.getHangarLevel());
		ogamePlanet.setResearchLab(orp.getResearchLabLevel());
		ogamePlanet.setMissileSilo(orp.getSiloLevel());
		ogamePlanet.setNaniteFactory(orp.getNanobotFactoryLevel());
		ogamePlanet.setTerraformer(orp.getTerraformerLevel());
	}
	
	public void getResearch(OgameSession ogameSession, OgamePlanet ogamePlanet) throws OgameException{
		HttpGet request = OgameRequestFactory.getResearchRequest(ogameSession, ogamePlanet);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
		
		OgameResponseParser orp = new OgameResponseParser(sb.toString());
		
		ogamePlanet.setEnergyTechnology(orp.getEnergyTechnology());
		ogamePlanet.setLaserTechnology(orp.getLaserTechnology());
		ogamePlanet.setIonTechnology(orp.getIonTechnology());
		ogamePlanet.setHyperspaceTechnology(orp.getHyperSpaceTechnology());
		ogamePlanet.setPlasmaTechnology(orp.getPlasmaTechnology());
		ogamePlanet.setCombustionDrive(orp.getCombustionDrive());
		ogamePlanet.setImpulseDrive(orp.getImpulseDrive());
		ogamePlanet.setHyperspaceDrive(orp.getHyperSpaceDrive());
		ogamePlanet.setEspionageTechnology(orp.getEspionageTechnology());
		ogamePlanet.setComputerTechnology(orp.getComputerTechnology());
		ogamePlanet.setAstrophysics(orp.getAstrophysics());
		ogamePlanet.setIntergalacticResearchNetwork(orp.getIntergalacticResearchNetwork());
		ogamePlanet.setGravitonTechnology(orp.getGravitonTechnology());
		ogamePlanet.setWeaponsTechnology(orp.getWeaponTechnology());
		ogamePlanet.setShieldingTechnology(orp.getShieldingTechnology());
		ogamePlanet.setArmourTechnology(orp.getArmourTechnology());
	}
	
	public void getShipyard(OgameSession ogameSession, OgamePlanet ogamePlanet) throws OgameException{
		HttpGet request = OgameRequestFactory.getShipyardRequest(ogameSession, ogamePlanet);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
		
		OgameResponseParser orp = new OgameResponseParser(sb.toString());
		
		ogamePlanet.setLightFighter(orp.getLightFighterQuantity());
		ogamePlanet.setHeavyFighter(orp.getHeavyFighterQuantity());
		ogamePlanet.setCruiser(orp.getCruiserQuantity());
		ogamePlanet.setBattleShip(orp.getBattleShipQuantity());
		ogamePlanet.setBattlecruiser(orp.getBattleCruiserQuantity());
		ogamePlanet.setBomber(orp.getBomberQuantity());
		ogamePlanet.setDestroyer(orp.getDestroyerQuantity());
		ogamePlanet.setDeathStar(orp.getDeathStarQuantity());
		ogamePlanet.setSmallCargo(orp.getSmallCargoQuantity());
		ogamePlanet.setLargeCargo(orp.getLargeCargoQuantity());
		ogamePlanet.setColonyShip(orp.getColonyShipQuantity());
		ogamePlanet.setRecycler(orp.getRecyclerQuantity());
		ogamePlanet.setEspionageProbe(orp.getEspionageProbeQuantity());
		ogamePlanet.setSolarSatellite(orp.getSolarSatellieLevel());
	}
	
	public void getDefense(OgameSession ogameSession, OgamePlanet ogamePlanet) throws OgameException{
		HttpGet request = OgameRequestFactory.getDefenseRequest(ogameSession, ogamePlanet);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
		
		OgameResponseParser orp = new OgameResponseParser(sb.toString());
		
		ogamePlanet.setRocketLauncher(orp.getRocketLauncherQuantity());
		ogamePlanet.setLightLaser(orp.getLightLaserQuantity());
		ogamePlanet.setHeavyLaser(orp.getHeavyLaserQuantity());
		ogamePlanet.setIonCannon(orp.getIonCannonQuantity());
		ogamePlanet.setGaussCannon(orp.getGaussCannonQuantity());
		ogamePlanet.setPlasmaTurret(orp.getPlasmaTurretQuantity());
		ogamePlanet.setSmallShieldDome(orp.getSmallShieldDome());
		ogamePlanet.setLargeShieldDome(orp.getLargeShieldDome());
		ogamePlanet.setAntiBallisticMissile(orp.getAntiBallisticMissileQuantity());
		ogamePlanet.setInterplanetaryMissile(orp.getInterPlanetaryMissileQuantity());
	}
	
	public void saveFleet(OgameSession ogameSession, OgamePlanet origin) throws OgameException {
		int i = ogameSession.getPlanets().indexOf(origin);
		int j = (i+1)%ogameSession.getPlanets().size();
		
		OgamePlanet destination = ogameSession.getPlanets().get(j);
		
		executeFleet2(ogameSession, origin, destination);
		executeFleet3(ogameSession, origin, destination);
		executeMovement(ogameSession, origin, destination);
	}
	
	private void executeFleet2(OgameSession ogameSession, OgamePlanet origin, OgamePlanet destination) throws OgameException{
		HttpPost request = OgameRequestFactory.getFleet2Request(ogameSession, origin, destination);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
	}
	
	private void executeFleet3(OgameSession ogameSession, OgamePlanet origin, OgamePlanet destination) throws OgameException{
		HttpPost request = OgameRequestFactory.getFleet3Request(ogameSession, origin, destination);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
	}
	
	private void executeMovement(OgameSession ogameSession, OgamePlanet origin, OgamePlanet destination) throws OgameException{
		HttpPost request = OgameRequestFactory.getMovementRequest(ogameSession, origin, destination);
		StringBuilder sb = executRequestAndCollectContent(request, this.httpClient);
	}
	
	
	
	public static void main(String[] args) throws Exception {
		String user = "rulix";
		String password = "11223344";
		String server = "uni58.ogame.com.es";
		
		DefaultHttpClient httpClient = new DefaultHttpClient();;
		OgameHttpExecutor oghe = new OgameHttpExecutor(httpClient);
		
		OgameSession ogameSession = oghe.login(server, user, password);
		
		if ( !ogameSession.isLoggedIn() ){
			System.err.println("Not logged in");
			System.exit(-1);
		}
		
		System.out.println("Logged in!!!");
		
		oghe.initialize(ogameSession);
		
		for (OgamePlanet planet : ogameSession.getPlanets()) {
//			oghe.getResources(ogameSession, planet);
//			oghe.getBuildings(ogameSession, planet);
//			oghe.getFacilities(ogameSession, planet);
//			oghe.getResearch(ogameSession, planet);
//			oghe.getShipyard(ogameSession, planet);
//			oghe.getDefense(ogameSession, planet);
		}
		
		//oghe.saveFleet(ogameSession, ogameSession.getPlanets().get(0));
		
		System.out.println("Planets: " + ogameSession.getPlanets());

		
		List<OgameFleetMovement> listFm = oghe.getFleetMovements(ogameSession);
		System.out.println("Fleet movements: " + listFm);
		
	}
	

}
